﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Jok.Server.Infrastructure
{
    internal delegate void SendCommandDelegate(JokCommand Command);

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerSession)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public abstract class JokService : IJokService
    {
        private const string TICKET_HEADER_NAME = "TicketHeader";

        /// <summary>
        /// All registered players
        /// </summary>
        public static Dictionary<Guid, JokUser> Tickets { get; set; }
        private static event SendCommandDelegate NotifyAllUsers;

        /// <summary>
        /// Gets current callback
        /// Note: Use only in methods which are called by user, otherwise it will be null
        /// </summary>
        public IJokServiceCallback CurrentCallBack
        {
            get { return OperationContext.Current.GetCallbackChannel<IJokServiceCallback>(); }
        }
        /// <summary>
        /// კონკრეტული კონექშენის ბილეთი
        /// </summary>
        public Guid CurrentTicket
        {
            get { return OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>(TICKET_HEADER_NAME, String.Empty); }
        }

        /// <summary>
        /// სტატიკური კონსტრუქტორი
        /// </summary>
        static JokService()
        {
            Tickets = new Dictionary<Guid, JokUser>();
        }

        /// <summary>
        /// Register player
        /// Warning: Use only in methods which are called by user, otherwise it will be null. It uses CurrentCallBack property
        /// </summary>
        /// <param name="Ticket">Player Ticket</param>
        /// <param name="CallBack"></param>
        public void RegisterTicket(Guid Ticket)
        {
            if (Tickets.ContainsKey(Ticket))
            {
                if (Tickets[Ticket].CallBack == CurrentCallBack)
                    return;

                UnregisterTicket(Ticket);
            }

            Tickets.Add(Ticket, new JokUser() { Ticket = Ticket, CallBack = CurrentCallBack });
            NotifyAllUsers += Tickets[Ticket].SendCommand;
        }
        /// <summary>
        /// Unregister Player
        /// </summary>
        /// <param name="Ticket"></param>
        public void UnregisterTicket(Guid Ticket)
        {
            if (!Tickets.ContainsKey(Ticket))
                return;

            NotifyAllUsers -= Tickets[Ticket].SendCommand;
            Tickets.Remove(Ticket);
        }

        /// <summary>
        /// Send command to all registered players
        /// </summary>
        /// <param name="Command">Command</param>
        public void SendToAll(JokCommand Command)
        {
            if (NotifyAllUsers != null)
                NotifyAllUsers(Command);
        }

        public virtual void CommandReceived(int UserId, Guid Ticket, JokCommand Command) { }
    }
}
